package com.warom.sdg.util;

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.ghgande.j2mod.modbus.ModbusException;
import com.warom.sdg.callback.PlcDataListener;

/**
 * Modbus通信帮助类
 * 提供常用的Modbus TCP通信操作示例
 */
public class ModbusHelper {
    private static final String TAG = "ModbusHelper";
    
    // Modbus地址范围定义
    public static final int COIL_START = 1;             // 00001
    public static final int COIL_END = 9999;            // 09999
    public static final int DISCRETE_INPUT_START = 10001;
    public static final int DISCRETE_INPUT_END = 19999;
    public static final int INPUT_REGISTER_START = 30001;
    public static final int INPUT_REGISTER_END = 39999;
    public static final int HOLDING_REGISTER_START = 40001;
    public static final int HOLDING_REGISTER_END = 49999;
    
    private ModbusTcpClient modbusTcpClient;
    private PlcDataListener dataListener;
    
    /**
     * 获取底层的ModbusTcpClient实例
     * @return ModbusTcpClient实例
     */
    public ModbusTcpClient getModbusTcpClient() {
        return modbusTcpClient;
    }
    
    /**
     * 构造函数
     * @param ipAddress PLC的IP地址
     * @param port 端口号
     * @param listener 数据监听器
     */
    public ModbusHelper(String ipAddress, int port, PlcDataListener listener) {
        modbusTcpClient = new ModbusTcpClient(ipAddress, port);
        this.dataListener = listener;
    }
    
    /**
     * 构造函数，使用默认端口502
     * @param ipAddress PLC的IP地址
     * @param listener 数据监听器
     */
    public ModbusHelper(String ipAddress, PlcDataListener listener) {
        modbusTcpClient = new ModbusTcpClient(ipAddress);
        this.dataListener = listener;
    }
    
    /**
     * 设置连接超时时间
     * @param timeout 超时时间（毫秒）
     */
    public void setTimeout(int timeout) {
        modbusTcpClient.setTimeout(timeout);
    }
    
    /**
     * 检查连接状态
     * @return 是否已连接
     */
    public boolean isConnected() {
        return modbusTcpClient != null && modbusTcpClient.isConnected();
    }
    
    /**
     * 连接到设备
     * 注意: 该方法将在后台线程执行网络操作，但可能会阻塞当前线程等待结果
     * @return 是否连接成功
     */
    public boolean connect() {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            Log.d(TAG, "从主线程调用connect，使用异步方式执行");
            // 从主线程调用，使用异步方式
            final boolean[] result = new boolean[1];
            final Object lock = new Object();
            
            // 创建一个一次性回调
            Runnable onComplete = new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        result[0] = modbusTcpClient.isConnected();
                        lock.notifyAll();
                    }
                }
            };
            
            // 在后台线程中执行连接
            new Thread(() -> {
                boolean connected = modbusTcpClient.connect();
                if (connected) {
                    // 在主线程上执行回调
                    new Handler(Looper.getMainLooper()).post(onComplete);
                } else {
                    // 连接失败
                    synchronized (lock) {
                        result[0] = false;
                        lock.notifyAll();
                    }
                }
            }).start();
            
            try {
                synchronized (lock) {
                    // 等待最多5秒
                    lock.wait(5000);
                    return result[0];
                }
            } catch (InterruptedException e) {
                Log.e(TAG, "等待连接过程被中断", e);
                return false;
            }
        } else {
            // 已经在后台线程，直接调用
            return modbusTcpClient.connect();
        }
    }
    
    /**
     * 断开与设备的连接
     */
    public void disconnect() {
        modbusTcpClient.disconnect();
    }
    
    /**
     * 尝试重新连接
     * 如果当前已连接，则先断开再重连
     * @return 是否重连成功
     */
    public boolean reconnect() {
        disconnect();
        return connect();
    }
    
    /**
     * 异步连接到PLC设备
     */
    public void connectAsync() {
        connectAsync(null);
    }
    
    /**
     * 异步连接到PLC设备，完成后执行指定的回调
     * @param callback 连接完成后要执行的回调，可以为null
     */
    public void connectAsync(final Runnable callback) {
        // 在Android 10 (API 29)及以上版本，AsyncTask已经被弃用
        // 使用线程池或Handler更加灵活
        new Thread(() -> {
            final boolean result = modbusTcpClient.connect();
            
            // 在主线程上执行回调
            new Handler(Looper.getMainLooper()).post(() -> {
                if (!result && dataListener != null) {
                    dataListener.onError("连接PLC失败");
                }
                
                if (callback != null) {
                    callback.run();
                }
            });
        }).start();
    }
    
    /**
     * 读取PLC寄存器
     * @param address 起始地址
     * @param count 寄存器数量
     * @param unitId 设备单元ID
     * @param isInputRegister 是否为输入寄存器，false为保持寄存器
     */
    public void readRegisters(final int address, final int count, final int unitId, final boolean isInputRegister) {
        // 添加详细日志
        Log.d(TAG, "开始读取" + (isInputRegister ? "输入" : "保持") + "寄存器: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId);
        
        new ReadRegistersAsyncTask(modbusTcpClient, dataListener, address, count, unitId, isInputRegister).execute();
    }
    
    private static class ReadRegistersAsyncTask extends AsyncTask<Void, Void, int[]> {
        private final ModbusTcpClient modbusTcpClient;
        private final PlcDataListener dataListener;
        private final int address;
        private final int count;
        private final int unitId;
        private final boolean isInputRegister;
        private String error;
        
        ReadRegistersAsyncTask(ModbusTcpClient modbusTcpClient, PlcDataListener dataListener, 
                               int address, int count, int unitId, boolean isInputRegister) {
            this.modbusTcpClient = modbusTcpClient;
            this.dataListener = dataListener;
            this.address = address;
            this.count = count;
            this.unitId = unitId;
            this.isInputRegister = isInputRegister;
        }
        
        @Override
        protected int[] doInBackground(Void... voids) {
            try {
                if (isInputRegister) {
                    return modbusTcpClient.readInputRegisters(address, count, unitId);
                } else {
                    return modbusTcpClient.readHoldingRegisters(address, count, unitId);
                }
            } catch (ModbusException e) {
                error = "读取寄存器失败: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId + ", 错误=" + e.getMessage();
                Log.e(TAG, error, e);
                return null;
            }
        }
        
        @Override
        protected void onPostExecute(int[] result) {
            if (dataListener != null) {
                if (result != null) {
                    String type = isInputRegister ? "InputRegister" : "HoldingRegister";
                    // 计算Modbus地址字符串
                    String addressStr = isInputRegister ? 
                        String.format("3%04d", address + 1) : 
                        String.format("4%04d", address + 1);
                    dataListener.onDataReceived(result, type, addressStr);
                } else {
                    dataListener.onError(error);
                }
            }
        }
    }
    
    /**
     * 读取PLC线圈或离散输入
     * @param address 起始地址
     * @param count 点数量
     * @param unitId 设备单元ID
     * @param isCoil 是否为线圈，false为离散输入
     */
    public void readBits(final int address, final int count, final int unitId, final boolean isCoil) {
        new ReadBitsAsyncTask(modbusTcpClient, dataListener, address, count, unitId, isCoil).execute();
    }
    
    private static class ReadBitsAsyncTask extends AsyncTask<Void, Void, boolean[]> {
        private final ModbusTcpClient modbusTcpClient;
        private final PlcDataListener dataListener;
        private final int address;
        private final int count;
        private final int unitId;
        private final boolean isCoil;
        private String error;
        
        ReadBitsAsyncTask(ModbusTcpClient modbusTcpClient, PlcDataListener dataListener,
                          int address, int count, int unitId, boolean isCoil) {
            this.modbusTcpClient = modbusTcpClient;
            this.dataListener = dataListener;
            this.address = address;
            this.count = count;
            this.unitId = unitId;
            this.isCoil = isCoil;
        }
        
        @Override
        protected boolean[] doInBackground(Void... voids) {
            try {
                if (isCoil) {
                    return modbusTcpClient.readCoils(address, count, unitId);
                } else {
                    return modbusTcpClient.readDiscreteInputs(address, count, unitId);
                }
            } catch (ModbusException e) {
                error = "读取线圈/离散量失败: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId + ", 错误=" + e.getMessage();
                Log.e(TAG, error, e);
                return null;
            }
        }
        
        @Override
        protected void onPostExecute(boolean[] result) {
            if (dataListener != null) {
                if (result != null) {
                    String type = isCoil ? "Coil" : "DiscreteInput";
                    // 计算Modbus地址字符串
                    String addressStr = isCoil ? 
                        String.format("%05d", address + 1) : 
                        String.format("1%04d", address + 1);
                    dataListener.onDataReceived(result, type, addressStr);
                } else {
                    dataListener.onError(error);
                }
            }
        }
    }
    
    /**
     * 写入单个寄存器
     * @param address 寄存器地址
     * @param value 写入的值
     * @param unitId 设备单元ID
     * @return 是否成功发起写入请求
     */
    public boolean writeSingleRegister(final int address, final int value, final int unitId) {
        try {
            WriteSingleRegisterAsyncTask task = new WriteSingleRegisterAsyncTask(modbusTcpClient, dataListener, address, value, unitId);
            task.execute();
            return true;
        } catch (Exception e) {
            Log.e(TAG, "写入寄存器失败: " + e.getMessage(), e);
            return false;
        }
    }
    
    private static class WriteSingleRegisterAsyncTask extends AsyncTask<Void, Void, Boolean> {
        private final ModbusTcpClient modbusTcpClient;
        private final PlcDataListener dataListener;
        private final int address;
        private final int value;
        private final int unitId;
        private String error;
        
        WriteSingleRegisterAsyncTask(ModbusTcpClient modbusTcpClient, PlcDataListener dataListener,
                                    int address, int value, int unitId) {
            this.modbusTcpClient = modbusTcpClient;
            this.dataListener = dataListener;
            this.address = address;
            this.value = value;
            this.unitId = unitId;
        }
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                return modbusTcpClient.writeSingleRegister(address, value, unitId);
            } catch (ModbusException e) {
                error = "写入寄存器失败: 地址=" + address + ", 值=" + value + ", 单元ID=" + unitId + ", 错误=" + e.getMessage();
                Log.e(TAG, error, e);
                return false;
            }
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            if (dataListener != null) {
                if (result) {
                    // 成功时返回写入的地址和值
                    String addressStr = String.format("4%04d", address + 1);
                    int[] values = new int[] { value };
                    dataListener.onDataReceived(values, "HoldingRegister", addressStr);
                } else {
                    dataListener.onError(error);
                }
            }
        }
    }
    
    /**
     * 写入多个寄存器
     * @param address 起始寄存器地址
     * @param values 写入的值数组
     * @param unitId 设备单元ID
     */
    public void writeMultipleRegisters(final int address, final int[] values, final int unitId) {
        new WriteMultipleRegistersAsyncTask(modbusTcpClient, dataListener, address, values, unitId).execute();
    }
    
    private static class WriteMultipleRegistersAsyncTask extends AsyncTask<Void, Void, Boolean> {
        private final ModbusTcpClient modbusTcpClient;
        private final PlcDataListener dataListener;
        private final int address;
        private final int[] values;
        private final int unitId;
        private String error;
        
        WriteMultipleRegistersAsyncTask(ModbusTcpClient modbusTcpClient, PlcDataListener dataListener,
                                       int address, int[] values, int unitId) {
            this.modbusTcpClient = modbusTcpClient;
            this.dataListener = dataListener;
            this.address = address;
            this.values = values;
            this.unitId = unitId;
        }
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                return modbusTcpClient.writeMultipleRegisters(address, values, unitId);
            } catch (ModbusException e) {
                error = "写入多个寄存器失败: 地址=" + address + ", 数量=" + values.length + ", 单元ID=" + unitId + ", 错误=" + e.getMessage();
                Log.e(TAG, error, e);
                return false;
            }
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            if (dataListener != null) {
                if (result) {
                    // 成功时返回写入的地址和值
                    String addressStr = String.format("4%04d", address + 1);
                    dataListener.onDataReceived(values, "HoldingRegister", addressStr);
                } else {
                    dataListener.onError(error);
                }
            }
        }
    }
    
    /**
     * 写入单个线圈
     * @param address 线圈地址
     * @param value 写入的布尔值
     * @param unitId 设备单元ID
     */
    public boolean writeSingleCoil(final int address, final boolean value, final int unitId) {
        try {
            WriteSingleCoilAsyncTask task = new WriteSingleCoilAsyncTask(modbusTcpClient, dataListener, address, value, unitId);
            task.execute();
            return true;
        } catch (Exception e) {
            Log.e(TAG, "写入线圈失败: " + e.getMessage(), e);
            return false;
        }
    }
    
    private static class WriteSingleCoilAsyncTask extends AsyncTask<Void, Void, Boolean> {
        private final ModbusTcpClient modbusTcpClient;
        private final PlcDataListener dataListener;
        private final int address;
        private final boolean value;
        private final int unitId;
        private String error;
        
        WriteSingleCoilAsyncTask(ModbusTcpClient modbusTcpClient, PlcDataListener dataListener,
                                int address, boolean value, int unitId) {
            this.modbusTcpClient = modbusTcpClient;
            this.dataListener = dataListener;
            this.address = address;
            this.value = value;
            this.unitId = unitId;
        }
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                return modbusTcpClient.writeCoil(address, value, unitId);
            } catch (ModbusException e) {
                error = "写入线圈失败: 地址=" + address + ", 值=" + value + ", 单元ID=" + unitId + ", 错误=" + e.getMessage();
                Log.e(TAG, error, e);
                return false;
            }
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            if (dataListener != null) {
                if (result) {
                    // 成功时返回写入的地址和值
                    String addressStr = String.format("%05d", address + 1);
                    boolean[] values = new boolean[] { value };
                    dataListener.onDataReceived(values, "Coil", addressStr);
                } else {
                    dataListener.onError(error);
                }
            }
        }
    }
    
    /**
     * 写入多个线圈
     * @param address 起始线圈地址
     * @param values 写入的布尔值数组
     * @param unitId 设备单元ID
     */
    public void writeMultipleCoils(final int address, final boolean[] values, final int unitId) {
        new WriteMultipleCoilsAsyncTask(modbusTcpClient, dataListener, address, values, unitId).execute();
    }
    
    private static class WriteMultipleCoilsAsyncTask extends AsyncTask<Void, Void, Boolean> {
        private final ModbusTcpClient modbusTcpClient;
        private final PlcDataListener dataListener;
        private final int address;
        private final boolean[] values;
        private final int unitId;
        private String error;
        
        WriteMultipleCoilsAsyncTask(ModbusTcpClient modbusTcpClient, PlcDataListener dataListener,
                                   int address, boolean[] values, int unitId) {
            this.modbusTcpClient = modbusTcpClient;
            this.dataListener = dataListener;
            this.address = address;
            this.values = values;
            this.unitId = unitId;
        }
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                return modbusTcpClient.writeMultipleCoils(address, values, unitId);
            } catch (ModbusException e) {
                error = "写入多个线圈失败: 地址=" + address + ", 数量=" + values.length + ", 单元ID=" + unitId + ", 错误=" + e.getMessage();
                Log.e(TAG, error, e);
                return false;
            }
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            if (dataListener != null) {
                if (result) {
                    // 成功时返回写入的地址和值
                    String addressStr = String.format("%05d", address + 1);
                    dataListener.onDataReceived(values, "Coil", addressStr);
                } else {
                    dataListener.onError(error);
                }
            }
        }
    }
    
    /**
     * 解析Modbus TCP请求报文
     * 将16进制字符串格式的报文解析为可读的参数
     * 例如: "00 00 00 00 00 06 01 03 00 00 00 28"
     * 
     * @param hexMessage 16进制字符串格式的Modbus TCP报文
     * @return 解析后的报文信息
     */
    public static ModbusMessage parseModbusHexMessage(String hexMessage) {
        ModbusMessage result = new ModbusMessage();
        
        // 去除空格并确保字符串有效
        String cleanHex = hexMessage.replaceAll("\\s+", "").trim();
        if (cleanHex.length() < 24) { // 至少需要12个字节
            result.error = "报文长度不足";
            return result;
        }
        
        try {
            // 解析事务标识符 (Transaction ID)
            result.transactionId = Integer.parseInt(cleanHex.substring(0, 4), 16);
            
            // 解析协议标识符 (Protocol ID, 通常为0)
            result.protocolId = Integer.parseInt(cleanHex.substring(4, 8), 16);
            
            // 解析长度 (Length)
            result.length = Integer.parseInt(cleanHex.substring(8, 12), 16);
            
            // 解析单元标识符 (Unit ID)
            result.unitId = Integer.parseInt(cleanHex.substring(12, 14), 16);
            
            // 解析功能码 (Function Code)
            result.functionCode = Integer.parseInt(cleanHex.substring(14, 16), 16);
            
            // 根据功能码解析后续数据
            switch (result.functionCode) {
                case 1: // 读线圈
                case 2: // 读离散输入
                case 3: // 读保持寄存器
                case 4: // 读输入寄存器
                    // 解析起始地址
                    result.startAddress = Integer.parseInt(cleanHex.substring(16, 20), 16);
                    // 解析寄存器/线圈数量
                    result.quantity = Integer.parseInt(cleanHex.substring(20, 24), 16);
                    break;
                
                case 5: // 写单个线圈
                case 6: // 写单个寄存器
                    // 解析地址
                    result.startAddress = Integer.parseInt(cleanHex.substring(16, 20), 16);
                    // 解析值
                    result.value = Integer.parseInt(cleanHex.substring(20, 24), 16);
                    break;
                
                case 15: // 写多个线圈
                case 16: // 写多个寄存器
                    // 需要更复杂的解析，这里略过
                    result.startAddress = Integer.parseInt(cleanHex.substring(16, 20), 16);
                    result.quantity = Integer.parseInt(cleanHex.substring(20, 24), 16);
                    result.dataLength = Integer.parseInt(cleanHex.substring(24, 26), 16);
                    // 解析数据值，这里只做简单示例
                    if (cleanHex.length() >= 26 + (result.dataLength * 2)) {
                        result.data = cleanHex.substring(26, 26 + (result.dataLength * 2));
                    }
                    break;
                
                default:
                    result.error = "不支持的功能码: " + result.functionCode;
            }
            
            // 设置功能描述
            result.setFunctionDescription();
            
        } catch (NumberFormatException | StringIndexOutOfBoundsException e) {
            result.error = "解析报文失败: " + e.getMessage();
            Log.e(TAG, "解析Modbus报文出错", e);
        }
        
        return result;
    }
    
    /**
     * 创建Modbus TCP请求报文
     * 根据参数生成16进制字符串格式的报文
     * 
     * @param functionCode 功能码
     * @param startAddress 起始地址
     * @param quantity 数量
     * @param unitId 单元ID
     * @return 16进制字符串格式的Modbus TCP报文
     */
    public static String createModbusHexMessage(int functionCode, int startAddress, int quantity, int unitId) {
        // 事务ID，自动生成
        int transactionId = (int)(Math.random() * 65535);
        
        // 协议ID，固定为0
        int protocolId = 0;
        
        // 长度，对于请求报文通常为6
        int length = 6;
        
        StringBuilder hexBuilder = new StringBuilder();
        
        // 添加事务ID
        hexBuilder.append(String.format("%04X", transactionId)).append(" ");
        
        // 添加协议ID
        hexBuilder.append(String.format("%04X", protocolId)).append(" ");
        
        // 添加长度
        hexBuilder.append(String.format("%04X", length)).append(" ");
        
        // 添加单元ID
        hexBuilder.append(String.format("%02X", unitId)).append(" ");
        
        // 添加功能码
        hexBuilder.append(String.format("%02X", functionCode)).append(" ");
        
        // 添加起始地址
        hexBuilder.append(String.format("%04X", startAddress)).append(" ");
        
        // 添加数量
        hexBuilder.append(String.format("%04X", quantity));
        
        return hexBuilder.toString();
    }
    
    /**
     * 执行Modbus报文命令
     * 
     * @param hexMessage 16进制字符串格式的报文
     * @return 是否执行成功
     */
    public boolean executeModbusHexCommand(String hexMessage) {
        Log.d(TAG, "执行Modbus报文命令: " + hexMessage);
        
        // 解析报文
        ModbusMessage message = parseModbusHexMessage(hexMessage);
        if (message == null) {
            if (dataListener != null) {
                dataListener.onError("解析Modbus报文失败");
            }
            return false;
        }
        
        // 根据功能码执行对应的命令
        try {
            switch (message.functionCode) {
                case 1: // 读线圈
                    readBits(message.startAddress, message.quantity, message.unitId, true);
                    break;
                
                case 2: // 读离散输入
                    readBits(message.startAddress, message.quantity, message.unitId, false);
                    break;
                
                case 3: // 读保持寄存器
                    readRegisters(message.startAddress, message.quantity, message.unitId, false);
                    break;
                
                case 4: // 读输入寄存器
                    readRegisters(message.startAddress, message.quantity, message.unitId, true);
                    break;
                
                case 5: // 写单个线圈
                    boolean coilValue = message.value != 0;
                    boolean coilResult = writeSingleCoil(message.startAddress, coilValue, message.unitId);
                    if (coilResult && dataListener != null) {
                        String addressStr = String.format("%05d", message.startAddress + 1);
                        boolean[] values = new boolean[] { coilValue };
                        dataListener.onDataReceived(values, "Coil", addressStr);
                    }
                    break;
                
                case 6: // 写单个寄存器
                    boolean regResult = writeSingleRegister(message.startAddress, message.value, message.unitId);
                    if (regResult && dataListener != null) {
                        String addressStr = String.format("4%04d", message.startAddress + 1);
                        int[] values = new int[] { message.value };
                        dataListener.onDataReceived(values, "HoldingRegister", addressStr);
                    }
                    break;
                
                case 15: // 写多个线圈
                case 16: // 写多个寄存器
                    if (dataListener != null) {
                        dataListener.onError("暂不支持直接从报文执行写多个线圈/寄存器操作");
                    }
                    return false;
                
                default:
                    if (dataListener != null) {
                        dataListener.onError("不支持的功能码: " + message.functionCode);
                    }
                    return false;
            }
            
            return true;
        } catch (Exception e) {
            Log.e(TAG, "执行Modbus命令失败: " + e.getMessage(), e);
            if (dataListener != null) {
                dataListener.onError("执行Modbus命令失败: " + e.getMessage());
            }
            return false;
        }
    }
    
    /**
     * 异步执行Modbus报文命令
     * 
     * @param hexMessage 16进制字符串格式的报文
     */
    public void executeModbusHexCommandAsync(final String hexMessage) {
        new ExecuteHexCommandAsyncTask(this, hexMessage, dataListener).execute();
    }
    
    private static class ExecuteHexCommandAsyncTask extends AsyncTask<Void, Void, Boolean> {
        private final ModbusHelper modbusHelper;
        private final String hexMessage;
        private final PlcDataListener dataListener;
        
        ExecuteHexCommandAsyncTask(ModbusHelper modbusHelper, String hexMessage, PlcDataListener dataListener) {
            this.modbusHelper = modbusHelper;
            this.hexMessage = hexMessage;
            this.dataListener = dataListener;
        }
        
        @Override
        protected Boolean doInBackground(Void... voids) {
            return modbusHelper.executeModbusHexCommand(hexMessage);
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            if (!result && dataListener != null) {
                dataListener.onError("执行Modbus命令失败");
            }
        }
    }
    
    /**
     * Modbus消息解析结果类
     */
    public static class ModbusMessage {
        public int transactionId;    // 事务标识符
        public int protocolId;       // 协议标识符
        public int length;           // 长度
        public int unitId;           // 单元标识符
        public int functionCode;     // 功能码
        public int startAddress;     // 起始地址
        public int quantity;         // 寄存器/线圈数量
        public int value;            // 值（用于写单个寄存器/线圈）
        public int dataLength;       // 数据长度（用于写多个寄存器/线圈）
        public String data;          // 数据内容（16进制字符串）
        public String error;         // 错误信息
        public String functionDescription; // 功能描述
        
        /**
         * 设置功能描述
         */
        private void setFunctionDescription() {
            switch (functionCode) {
                case 1:
                    functionDescription = "读线圈";
                    break;
                case 2:
                    functionDescription = "读离散输入";
                    break;
                case 3:
                    functionDescription = "读保持寄存器";
                    break;
                case 4:
                    functionDescription = "读输入寄存器";
                    break;
                case 5:
                    functionDescription = "写单个线圈";
                    break;
                case 6:
                    functionDescription = "写单个寄存器";
                    break;
                case 15:
                    functionDescription = "写多个线圈";
                    break;
                case 16:
                    functionDescription = "写多个寄存器";
                    break;
                default:
                    functionDescription = "未知功能码: " + functionCode;
            }
        }
        
        @Override
        public String toString() {
            if (error != null) {
                return "错误: " + error;
            }
            
            StringBuilder sb = new StringBuilder();
            sb.append("Modbus报文解析结果:\n");
            sb.append("事务ID: ").append(transactionId).append("\n");
            sb.append("协议ID: ").append(protocolId).append("\n");
            sb.append("长度: ").append(length).append("\n");
            sb.append("单元ID: ").append(unitId).append("\n");
            sb.append("功能码: ").append(functionCode).append(" (").append(functionDescription).append(")\n");
            sb.append("起始地址: ").append(startAddress).append("\n");
            
            switch (functionCode) {
                case 1:
                case 2:
                case 3:
                case 4:
                    sb.append("数量: ").append(quantity);
                    break;
                case 5:
                case 6:
                    sb.append("值: ").append(value);
                    break;
                case 15:
                case 16:
                    sb.append("数量: ").append(quantity).append("\n");
                    sb.append("数据长度: ").append(dataLength).append("\n");
                    sb.append("数据: ").append(data);
                    break;
            }
            
            return sb.toString();
        }
    }
    
    /**
     * 读取保持寄存器
     * @param address 起始地址
     * @param count 寄存器数量
     * @param unitId 设备单元ID
     */
    public void readHoldingRegisters(int address, int count, int unitId) {
        Log.d(TAG, "调用readHoldingRegisters: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId);
        readRegisters(address, count, unitId, false);
    }
    
    /**
     * 读取输入寄存器
     * @param address 起始地址
     * @param count 寄存器数量
     * @param unitId 设备单元ID
     */
    public void readInputRegisters(int address, int count, int unitId) {
        Log.d(TAG, "调用readInputRegisters: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId);
        readRegisters(address, count, unitId, true);
    }
    
    /**
     * 读取线圈
     * @param address 起始地址
     * @param count 线圈数量
     * @param unitId 设备单元ID
     */
    public void readCoils(int address, int count, int unitId) {
        Log.d(TAG, "调用readCoils: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId);
        readBits(address, count, unitId, true);
    }
    
    /**
     * 读取离散输入
     * @param address 起始地址
     * @param count 输入点数量
     * @param unitId 设备单元ID
     */
    public void readDiscreteInputs(int address, int count, int unitId) {
        Log.d(TAG, "调用readDiscreteInputs: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId);
        readBits(address, count, unitId, false);
    }
    
    /**
     * Modbus寄存器类型枚举
     */
    public enum ModbusRegisterType {
        COIL,               // 线圈
        DISCRETE_INPUT,     // 离散输入
        INPUT_REGISTER,     // 输入寄存器
        HOLDING_REGISTER    // 保持寄存器
    }
    
    /**
     * Modbus地址信息类
     */
    public static class ModbusAddressInfo {
        public ModbusRegisterType type;  // 寄存器类型
        public int address;              // 协议地址（0-based）
        public String typeDescription;   // 类型描述
    }
    
    /**
     * 解析Modbus地址
     * 支持的格式：
     * - 00001-09999: 线圈
     * - 10001-19999: 离散输入
     * - 30001-39999: 输入寄存器
     * - 40001-49999: 保持寄存器
     * 
     * @param addressStr 地址字符串，例如"40001"
     * @return 解析后的地址信息，如果解析失败返回null
     */
    public static ModbusAddressInfo parseModbusAddress(String addressStr) {
        try {
            int fullAddress = Integer.parseInt(addressStr);
            
            ModbusAddressInfo info = new ModbusAddressInfo();
            
            // 根据地址范围判断类型
            if (fullAddress >= COIL_START && fullAddress <= COIL_END) {
                info.type = ModbusRegisterType.COIL;
                info.address = fullAddress - 1; // Modbus协议地址从0开始
                info.typeDescription = "线圈";
                return info;
            } else if (fullAddress >= DISCRETE_INPUT_START && fullAddress <= DISCRETE_INPUT_END) {
                info.type = ModbusRegisterType.DISCRETE_INPUT;
                info.address = fullAddress - 10001; // 协议地址 = 实际地址 - 10001
                info.typeDescription = "离散输入";
                return info;
            } else if (fullAddress >= INPUT_REGISTER_START && fullAddress <= INPUT_REGISTER_END) {
                info.type = ModbusRegisterType.INPUT_REGISTER;
                info.address = fullAddress - 30001; // 协议地址 = 实际地址 - 30001
                info.typeDescription = "输入寄存器";
                return info;
            } else if (fullAddress >= HOLDING_REGISTER_START && fullAddress <= HOLDING_REGISTER_END) {
                info.type = ModbusRegisterType.HOLDING_REGISTER;
                info.address = fullAddress - 40001; // 协议地址 = 实际地址 - 40001
                info.typeDescription = "保持寄存器";
                return info;
            }
            
            return null; // 无效地址
        } catch (NumberFormatException e) {
            Log.e(TAG, "地址解析错误: " + addressStr, e);
            return null;
        }
    }
    
    /**
     * 读取指定Modbus地址的数据
     * 
     * @param addressStr Modbus地址字符串，例如"40001"
     * @param count 读取数量
     * @param unitId 单元ID
     * @return 是否成功发起读取请求
     */
    public boolean readAddress(String addressStr, int count, int unitId) {
        ModbusAddressInfo addressInfo = parseModbusAddress(addressStr);
        if (addressInfo == null) {
            Log.e(TAG, "无效的Modbus地址: " + addressStr);
            if (dataListener != null) {
                dataListener.onError("无效的Modbus地址: " + addressStr);
            }
            return false;
        }
        
        try {
            // 确保连接状态良好
            if (!modbusTcpClient.isConnected()) {
                Log.d(TAG, "读取前检测到连接已断开，尝试重连");
                if (!modbusTcpClient.keepAlive()) {
                    Log.e(TAG, "无法重新连接到设备，无法读取地址: " + addressStr);
                    if (dataListener != null) {
                        dataListener.onError("连接失败，无法读取地址");
                    }
                    return false;
                }
            }
            
            // 根据解析出的地址类型调用对应的读取方法
            switch (addressInfo.type) {
                case COIL:
                    readCoils(addressInfo.address, count, unitId);
                    break;
                case DISCRETE_INPUT:
                    readDiscreteInputs(addressInfo.address, count, unitId);
                    break;
                case INPUT_REGISTER:
                    readInputRegisters(addressInfo.address, count, unitId);
                    break;
                case HOLDING_REGISTER:
                    readHoldingRegisters(addressInfo.address, count, unitId);
                    break;
                default:
                    return false;
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "读取地址失败: " + addressStr, e);
            if (dataListener != null) {
                dataListener.onError("读取地址失败: " + e.getMessage());
            }
            return false;
        }
    }
    
    /**
     * 写入指定Modbus地址的数据
     * 
     * @param addressStr Modbus地址字符串，例如"40001"
     * @param value 写入的值
     * @param unitId 单元ID
     * @return 是否成功发起写入请求
     */
    public boolean writeAddress(String addressStr, Object value, int unitId) {
        ModbusAddressInfo addressInfo = parseModbusAddress(addressStr);
        if (addressInfo == null) {
            Log.e(TAG, "无效的Modbus地址: " + addressStr);
            if (dataListener != null) {
                dataListener.onError("无效的Modbus地址: " + addressStr);
            }
            return false;
        }
        
        try {
            // 根据解析出的地址类型调用对应的写入方法
            switch (addressInfo.type) {
                case COIL:
                    // 写入线圈需要布尔值
                    boolean boolValue;
                    if (value instanceof Boolean) {
                        boolValue = (Boolean) value;
                    } else if (value instanceof Number) {
                        boolValue = ((Number) value).intValue() != 0;
                    } else if (value instanceof String) {
                        String strValue = ((String) value).trim().toLowerCase();
                        boolValue = strValue.equals("true") || strValue.equals("1") || 
                                   strValue.equals("on") || strValue.equals("yes");
                    } else {
                        Log.e(TAG, "无效的线圈值类型: " + value.getClass().getName());
                        if (dataListener != null) {
                            dataListener.onError("无效的线圈值类型: " + value.getClass().getName());
                        }
                        return false;
                    }
                    return writeSingleCoil(addressInfo.address, boolValue, unitId);
                    
                case HOLDING_REGISTER:
                    // 写入寄存器需要整数值
                    int intValue;
                    if (value instanceof Number) {
                        intValue = ((Number) value).intValue();
                    } else if (value instanceof String) {
                        try {
                            intValue = Integer.parseInt((String) value);
                        } catch (NumberFormatException e) {
                            Log.e(TAG, "无法将字符串转换为整数: " + value);
                            if (dataListener != null) {
                                dataListener.onError("无法将字符串转换为整数: " + value);
                            }
                            return false;
                        }
                    } else {
                        Log.e(TAG, "无效的寄存器值类型: " + value.getClass().getName());
                        if (dataListener != null) {
                            dataListener.onError("无效的寄存器值类型: " + value.getClass().getName());
                        }
                        return false;
                    }
                    return writeSingleRegister(addressInfo.address, intValue, unitId);
                    
                case DISCRETE_INPUT:
                case INPUT_REGISTER:
                    // 离散输入和输入寄存器是只读的
                    Log.e(TAG, "不能写入只读地址: " + addressStr);
                    if (dataListener != null) {
                        dataListener.onError("不能写入只读地址: " + addressStr);
                    }
                    return false;
                    
                default:
                    return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "写入地址失败: " + addressStr, e);
            if (dataListener != null) {
                dataListener.onError("写入地址失败: " + e.getMessage());
            }
            return false;
        }
    }
} 